﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.Dynamic;
using System.Text;

namespace T.FAS.Runtime.Base.Entity
{
    public static class TResultSchemaBuilder
    {
        public static TResult BuildEmptyTResultBySchema(TSchema schema)
        {
            var result = new TResult();
            if (schema.MetadataType == TEntityType.SGEO)
            {
                result = null;
            }
            else
            {
                result = BuildFASTResultSchema(schema);
            }
            return result;
        }
        private static TResult BuildFASTResultSchema(TSchema schema)
        {
            if (schema == null || schema.Entity == null)
                throw new ArgumentNullException("TResultBuilder.BuildTResult Error,shcema is null");
            
            var result = new TCommonResult<TRecord>();
            result.ResultType = schema.ResultType;
            result.Record = new TRecord();
            result.ActionID = schema.ActionID;
            result.ActionCode = schema.ActionCode;
            result.ActionName = schema.ActionName;
            
            result.List = new TArray<TRecord>(schema.Entity);
            result.EntityType = schema.MetadataType;
            var dataResultType = schema.ResultType;
            if (schema.MetadataType == TEntityType.DQ)
            {
                BuildFASDQResultSchema(schema, result, dataResultType);
            }
            else
            {
                BuildFASCDOResultSchema(schema, result, dataResultType);
            }
            return result;
        }

        private static void BuildFASCDOResultSchema(TSchema schema, TCommonResult<TRecord> result, DataType dataResultType)
        {
            if (dataResultType == DataType.Record)
            {
                var propertiesDic = new Dictionary<string, object>();
                BuildRecordProperties(schema.Entity, propertiesDic);
                var parentPropertiesDic = new Dictionary<string, object>()
                {
                    { schema.Entity.MetadataCode,new TRecord(propertiesDic)}
                };

                result.Record = new TRecord(parentPropertiesDic);
                result.Count = 1;
                result.List = null;
            }
            else
            {
                var listPropertiesDic = new Dictionary<string, object>();

                var propertiesDic = new Dictionary<string, object>();
                BuildRecordProperties(schema.Entity, propertiesDic);
                listPropertiesDic.Add("Current", propertiesDic);

                result.List.Add(new TRecord(listPropertiesDic));
                result.List.Rows = 0;
            }
        }
        private static void BuildFASDQResultSchema(TSchema schema, TCommonResult<TRecord> result, DataType dataResultType)
        {
            if (schema.Entity.Attributes == null || schema.Entity.Attributes.Count <= 0)
                throw new Exception("DQ Attributes is nulll");
            var propertiesDic = new Dictionary<string, object>();
            schema.Entity.Attributes.ForEach(x =>
            {
                if (x.DataType == DataType.Record)
                {
                    if (x.Entity != null && x.Entity.Attributes != null && x.Entity.Attributes.Count > 0)
                    {
                        x.Entity.Attributes.ForEach(p =>
                        {
                            if (!p.IsVirtual)
                            {
                                if (p.DataType != DataType.List && p.DataType != DataType.Record)
                                {
                                    propertiesDic[p.Code] = "";
                                }
                                else
                                {
                                    throw new Exception($"DQ {schema.Entity.MetadataCode} DO {x.Entity.MetadataCode} Attribute {p.Code} type can not be list or record");
                                }
                            }
                        });
                    }
                }
                else if (x.DataType != DataType.List)
                {
                    propertiesDic[x.Code] = "";
                }
                else
                {
                    throw new Exception($"DQ {schema.Entity.MetadataCode} Attribute {x.Code} can not be list");
                }
            });
            result.List.Add(new TRecord(propertiesDic));
            result.List.Rows = 0;
        }

        /// <summary>
        /// 构造Record的属性
        /// </summary>
        /// <param name="row">数据行</param>
        /// <param name="tables">数据集合</param>
        /// <param name="entity">实体结构</param>
        /// <param name="propertiesDic">属性集合</param>
        private static void  BuildRecordProperties(TEntity entity,Dictionary<string,object> propertiesDic)
        {
            entity.Attributes.ForEach(p =>
            {
                if (!p.IsVirtual)
                {
                    if (p.DataType == DataType.List)
                    {
                        propertiesDic[p.Code] = BuildListRecords(p.Entity);
                    }
                    else if (p.DataType == DataType.Record)
                    {
                        propertiesDic[p.Code]= BuildRecord(p.Entity);
                    }
                    else
                    {
                        propertiesDic[p.Code] =  "";
                    }
                }
            });
        }
        private static void BuildCurrentMethodNode(List<TListMethod> methods, TEntity entity, List<TRecord> recordList)
        {
            var listMethod = methods.Find(x => x.Code.Equals("list", StringComparison.OrdinalIgnoreCase));
            if (listMethod == null || listMethod.SubMethods == null || listMethod.SubMethods.Count <= 0)
                return;

            var currentMethod = listMethod.SubMethods.Find(x => x.Code.Equals("current", StringComparison.OrdinalIgnoreCase));
            if (currentMethod == null)
                return;
            var properties = new Dictionary<string, object>();
            if (currentMethod.Code.ToLower().Equals("current"))
            {
                properties.Add("Current", recordList[0]);
            }
            recordList.Add(new TRecord(properties));
        }

        /// <summary>
        /// 构造Record数据
        /// </summary>
        /// <param name="tables">数据集合</param>
        /// <param name="entity">entity结构</param>
        /// <returns></returns>
        private static TRecord BuildRecord(TEntity entity)
        {
            TRecord record = new TRecord();
            var propertiesDic = new Dictionary<string, object>();
            entity.Attributes.ForEach(p =>
            {
                if (!p.IsVirtual)
                {
                    if (p.DataType == DataType.List)
                    {
                        propertiesDic.Add(p.Code, BuildListRecords(p.Entity));
                    }
                    else if (p.DataType == DataType.Record)
                    {
                        propertiesDic.Add(p.Code,BuildRecord(p.Entity));
                    }
                    else
                    {
                        propertiesDic.Add(p.Code,"");
                    }
                }
            });
            record = new TRecord(propertiesDic);
            return record;
        }
        /// <summary>
        /// 构造ListRecord
        /// </summary>
        /// <param name="dt">数据表</param>
        /// <param name="ds">数据集合</param>
        /// <param name="entity">实体结构</param>
        /// <returns></returns>
        private static List<TRecord> BuildListRecords(TEntity entity)
        {
            List<TRecord> list = new List<TRecord>();
            TRecord data = BuildRecord(entity);
            list.Add(data);
            return list;
        }

    }
}
